﻿using System;
using System.Collections.Generic;
using CarlosAg.ExcelXmlWriter;
using SdmxMl.Common;
using SdmxMl.Manager;
using SdmxMl.Structure;
using SdmxMl.GenericMetadata;

namespace SdmxMl.Excel
{
    /// <summary>
    /// Export metadataset in Excel.
    /// Limited usage as reparted tags content is not supported by this class
    /// </summary>
    public class ExcelExportGenericMetaset : ExcelExportBase
    {
        #region Internal Members

        private SmManager smManager;
        private MetadataSetType  metaSet;
        private MetadataStructureDefinitionType msd;
        private ReportStructureType report;
        private int itemCount;

        #endregion

        #region C'tor

        /// <summary>C'tor with specified artefact to transform</summary>
        /// <param name="mSet">The generic metadataset</param>
        /// <param name="mdef"> the MSD describing metaset format</param>
        /// <param name="sm">Container with copy of memory content already loaded</param>
        public ExcelExportGenericMetaset(MetadataSetType mSet, MetadataStructureDefinitionType mdef, SmManager sm)
        {
            metaSet = mSet;
            msd = mdef;
            smManager = sm;

            //check null param
            if (msd == null)
                throw new ArgumentNullException("MSD");
            if (metaSet == null)
                throw new ArgumentNullException("MetadataSet");
            if (smManager == null)
                throw new ArgumentNullException("SM Container");

            // check correct msd is refered
            if (metaSet.MetadataStructureRef.FullIdent != msd.FullIdent)
                throw new ArgumentException("Incorrect metadata structure received for metadataset");

            report = msd.ReportStructureList.LocateItem(metaSet.ReportRef);
            if (report == null)
                throw new ArgumentException("Incorrect report reference [" + metaSet.ReportRef + "], it does not exist in associated MSD");


        }

        #endregion

        #region Header

        private void RecurseHeaderReport(MetadataAttributeTypeList metaList)
        {
             // Column count depends of languages requested
            foreach (MetadataAttributeType meta in metaList)
            {
                // if presentational ignore in export
                if (meta.MetaOccurence.IsPresentational == false)
                {

                    // if multiLingual prepares a column for each lang
                    if (meta.TextFormat.isMultiLingual)
                    {
                        foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                            headerColitems.Add(meta.ConceptInfo.Id + "_" + lg);
                    }
                    else
                        headerColitems.Add(meta.ConceptInfo.Id);
                }

                RecurseHeaderReport(meta.MetadataAttributeList);
            }
                


                
       }
        /// <summary>
        /// Generate Header row names for a report page
        /// </summary>
        private void GenerateHeaderNames()
        {
            headerColitems = new List<string>(32);
            // Keys
            foreach (IdentifierComponentType key in msd.TargetIdentifiers.FullTargetIdentifier.IdentifierComponentList)
                headerColitems.Add(key.Id);

            RecurseHeaderReport(report.MetadataAttributeList);

            // Do not support annotations in export as each reported value can have as many annotations as desired (too big)
            // anInventory = new AnnotationInventory();

        }
        #endregion

        #region Export

        public override void Export()
        {
            GenerateBook("SMS", "OFS");
            GenerateWorksheetArtefact(metaSet);

            GenerateHeaderNames();
            sheet = GenerateWorksheetHeader(headerColitems.ToArray(), "Reported", 10);

            itemCount = 0;
            foreach (AttributeValueSetType atv in metaSet.AttributeValueSetList)
            {
                FillRow(atv);
                ++itemCount;
            }

            // Update sheet count
            sheet.Table.ExpandedRowCount = 1 + itemCount;
        }

        protected void FillRow(AttributeValueSetType atv)
        {
            if (atv != null)
            {
                WorksheetRow row = sheet.Table.Rows.Add();
                // Keys
                foreach (IdentifierComponentType key in msd.TargetIdentifiers.FullTargetIdentifier.IdentifierComponentList)
                    AddCell(row, atv.TargetValuesTypeList[key.Id]);

                // ReportedValues
                FillRowRecurse(row, report.MetadataAttributeList, atv);
            }
        }

        private void FillRowRecurse(WorksheetRow row, MetadataAttributeTypeList metaList, AttributeValueSetType atv)
        {
              // Column count depends of languages requested
            foreach (MetadataAttributeType meta in metaList)
            {
                // if presentational ignore in export
                if (meta.MetaOccurence.IsPresentational == false)
                {
                    ReportedAttributeTypeList raList = new ReportedAttributeTypeList();
                    atv.ReportedAttributeList.GetReportedAttributeListForConcept(meta.ConceptInfo.Id, raList);
                    if (raList.Count > 1)
                        throw new ApplicationException("Multiple tag for a concept is not yet supported");
                    ReportedAttributeType ra = new ReportedAttributeType();
                    if (raList.Count == 1)
                        ra = raList[0];

                    // if multiLingual prepares a column for each lang
                    if (meta.TextFormat.isMultiLingual)
                        FillMultilangCells(row, ra.InternationalizedValue);
                    else
                        AddCell(row, ra.Value.ToString());
                }

                FillRowRecurse(row, meta.MetadataAttributeList, atv);
            }
       }

        private void FillMultilangCells(WorksheetRow row, MultiLang ml)
        {
            if (ml != null && ml.IsEmpty == false)
            {
                foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                    AddCell(row, ml.GetIfDefinedForLanguage(lg));
            }
            else
            {
                foreach (string lg in SdmxMl.Common.LangSupport.SupportedLanguages)
                    AddCell(row, string.Empty);
            }
        }
        #endregion
    }
}
